import { ApiDoc } from './../../../tsHelpers'
import { swagger2GenUrl, oas3GenUrl } from '@/config'
import ora from 'ora'
import axios, { AxiosResponse } from 'axios'
import { downloadFile } from '@/utils/downloadFile'
import { ConvertRes, DownloadFileRes } from '@/tsHelpers'
import fs from 'fs-extra'
import path from 'path'
import { rimraf } from 'rimraf'
import AdmZip from 'adm-zip'

export const D_downloadFile = async (
  lastData: ConvertRes
): Promise<DownloadFileRes> => {
  const startMsg = '文件生成中... \n'
  const errMsg = '文件生成失败 \n'

  const spinner = ora(startMsg).start()
  let filePaths: Array<string | undefined> = []
  try {
    filePaths = await Promise.all(lastData.apiDocs.map(item => {
      return new Promise<string | undefined>(async (resolve) => {
        if (!item) {
          resolve(undefined)
          return
        }
        const result = await getFileResponse(lastData, item)
        if (result?.status!=200) {
          spinner.warn(item.name + '：文件下载失败，'+ result?.data)
          resolve(undefined)
          return
        }
        rimraf.rimrafSync(`${lastData.output_dir}/${item.name}`)
        const filePath = await downloadFile(result, `${lastData.output_dir}/${item.name}`)
        await extractFile(
          filePath,
          path.resolve(`${lastData.output_dir}/${item.name}`),
          Boolean(lastData.clean)
        )
        spinner.info(item.name + '：文件下载成功')
        resolve(filePath)
      })
    }))
  } catch (error) {
    spinner.fail(errMsg)
    filePaths = []
    throw error
  }
  return { ...lastData, filePaths }
}

const getFileResponse = async (lastData: ConvertRes, apiDoc: ApiDoc) => {
  if (apiDoc.isOAS3) {
    try {
      const response = await axios.post(
        oas3GenUrl,
        {
          lang: apiDoc.lang,
          spec: apiDoc.spec,
          type: apiDoc.type,
        },
        {
          responseType: 'stream',
        }
      )
      return response
    } catch (error) {
      return {
        data: error
      } as AxiosResponse<any, any>
    }
  } else {
    try {
      const res = await axios.post(swagger2GenUrl + '/' + lastData.client_type, {
        spec: apiDoc.spec,
      })
      if (res.data.link) {
        const response = await axios.get(res.data.link, {
          responseType: 'stream',
        })
        return response
      }
    } catch (error) {
      return {
        data: error
      } as AxiosResponse<any, any>
    }
  }
}

const extractFile = async (
  filePath: string,
  outputPath: string,
  clean: boolean
) => {
  return new Promise<void>((resolve, reject) => {
    try {
      const zip = new AdmZip(filePath)
      zip.getEntries().forEach((entry) => {
        if (!/\/$/.test(entry.entryName)) {
          // 解压文件
          fs.ensureDirSync(path.dirname(`${outputPath}/${entry.entryName}`))
          const content = entry.getData()
          fs.writeFileSync(`${outputPath}/${entry.entryName}`, content)
        }
      })
      if (clean) {
        rimraf.moveRemoveSync(outputPath + '/.swagger-codegen')
        rimraf.moveRemoveSync(outputPath + '/.gitignore')
        rimraf.moveRemoveSync(outputPath + '/.npmignore')
        rimraf.moveRemoveSync(outputPath + '/package.json')
        rimraf.moveRemoveSync(outputPath + '/.swagger-codegen-ignore')
        rimraf.moveRemoveSync(outputPath + '/git_push.sh')
      }
      resolve()
    } catch (error) {
      reject(error)
      return
    }
  })
}
